package com.group2.operations.config;

import com.group2.operations.shiro.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
//    @Autowired
//    private RedisTemplate redisTemplate;

    //注入密码校验规则
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式为MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次数
        credentialsMatcher.setHashIterations(8);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);

        return credentialsMatcher;
    }

    //创建自定义Realm并注入密码校验规则
    @Bean
    public AdminRealm adminRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) {
        AdminRealm realm =  new AdminRealm();
        realm.setAuthenticationCachingEnabled(true);
        realm.setCredentialsMatcher(matcher);
        return realm;
    }

    //创建安全管理器WebSecurityManager，注入自定义的Realm
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("adminRealm") AdminRealm adminRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置session管理器
        securityManager.setSessionManager(sessionManager());

        //关联Realm
        securityManager.setRealm(adminRealm);
        return securityManager;
    }

    //创建ShiroFilter过滤器并注入securityManager
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager webSecurityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(webSecurityManager);

        //添加Shiro内置过滤器
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/admin/login", "anon");
        filterMap.put("/admin/department/agree", "authc,perms[admin_dep:track]");
        filterMap.put("/admin/department/trackall", "authc,perms[admin_dep:track]");
        filterMap.put("/admin/department/reject", "authc,perms[admin_dep:track]");
        filterMap.put("/admin/corporation/trackall", "authc,perms[admin_co:track]");
        filterMap.put("/admin/corporation/reject", "authc,perms[admin_co:track");
        filterMap.put("/admin/agent/client/*", "authc,perms[agent:client]");
        filterMap.put("/admin/department/trackall/*", "authc,perms[admin_dep:track]");
        filterMap.put("/admin/corporation/trackall/*", "authc,perms[admin_co:track]");

        //filterMap.put("/user/add", "authc,perms[test1]");

        bean.setFilterChainDefinitionMap(filterMap);

        //添加自定义过滤器
        Map<String, Filter> filters = bean.getFilters();
        filters.put("authc", new CORSAuthenticationFilter());
        filters.put("perms", new CORSAuthorizationFilter());
        bean.setFilters(filters);

        return bean;
    }

    //创建SessionManager
    @Bean
    public SessionManager sessionManager() {
        MyWebSessionManager sessionManager = new MyWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

    //创建自定义DAO
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO dao = new RedisSessionDAO();
//        dao.setRedisTemplate(redisTemplate);
        return dao;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn(value = {"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager webSecurityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(webSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
